<?php
namespace App\Controller;

use app\BaseController;
use finfo;
use think\Request;
use think\Token;
use app\service\Uploadservice;

class Files extends BaseController
{
    public function __construct(\think\App $app, Token $token, Uploadservice $upload)
    {
        $this->app = $app;
        $this->request = $this->app->request;

        $this->token = $token;
        $this->upload = $upload;

        $this->UserModel = new \app\common\model\User;
        $this->HandleModel = new \app\common\model\Handle;
        $this->FilesModel = new \app\common\model\Files;
        $this->ProjectModel = new \app\common\model\Project;
        $this->RelevanceModel = new \app\common\model\Relevance;
    }

    //获取文件列表
    public function list()
    {
        if ($this->request->isGet()) {
            $proid = $this->request->param('proid', 0, 'trim');
            $userid = $this->request->param('userid', 0, 'trim');

            if (empty($proid) || empty($userid)) {
                return json(error_ful('账号或项目不存在'));
            }

            // 检查文件夹类型
            $proInfo = $this->ProjectModel->where('id', $proid)->find();
            if (empty($proInfo)) {
                return json(error_ful('文件夹不存在'));
            }

            $relevanceInfo = null;
            if ($proInfo['protocol'] == 'protected') {
                $where = [
                    'proid' => $proid,
                    'userid' => $userid
                ];
                $relevanceInfo = $this->RelevanceModel->where($where)->find();
                if (empty($relevanceInfo)) {
                    return json(error_ful('无权访问'));
                }
            }

            // 获取父级文件夹下面的文件夹id
            $proidList = $this->ProjectModel->where('parentid', $proid)->column('id');
            // 获取文件夹
            $where = [
                'userid' => $userid,
                'deletetime' => null
            ];
            $proList = $this->RelevanceModel
                ->with(['project'])
                ->where($where)
                ->where('proid', 'in', $proidList)
                ->select();

            $where = ['deletetime' => null, 'proid' => $proid];
            $fileList = $this->FilesModel->where($where)->select();
            if (count($fileList) <= 0 && count($proList) <= 0) {
                return json(error_ful('暂无文件'));
            } else {
                $data = [
                    'proList' => $proList,
                    'fileList' => $fileList,
                ];
                if(!empty($relevanceInfo)){
                    $data['auth'] = $relevanceInfo ['auth'];
                }

                return json(success_ful('文件列表', $data));
            }
        }
    }



    //上传文件
    public function upload()
    {
        if ($this->request->isPost()) {
            $userid = $this->request->param('userid', 0, 'trim');
            $proid = $this->request->param('proid', 0, 'trim');

            $projectInfo = $this->ProjectModel->where('id', $proid)->find();
            if (empty($projectInfo)) {
                return json(error_ful('项目不存在'));
            }

            // 文件储存目录
            $res = file_upload($projectInfo['backage']);
            if ($res['status'] == false) {
                // 上传失败
                return json(error_ful($res['message']));
            }

            // 检查账号权限
            if (empty($userid)) {
                return json(error_ful('账号不存在'));
            }
            $authInfo = $this->RelevanceModel->where(['proid' => $proid, 'userid' => $userid])->find();
            if (($authInfo['auth'] ?? 0) * 1 < 3) {
                return json(error_ful('权限不足'));
            }

            // 开启事务
            $this->HandleModel->startTrans();
            $this->FilesModel->startTrans();

            // 先记录操作
            $handleDate = [
                'userid' => $userid,
                'time' => time(),
                'proid' => $proid,
                'filename' => $res['base_name'],
                'handtype' => 'upload'
            ];

            $handStatus = $this->HandleModel->save($handleDate);
            if ($handStatus === false) {
                return json(error_ful('记录操作失败'));
            }

            $fileDate = [
                'filename' => $res['base_name'],
                'proid' => $proid,
                'suffix' => $res['extension'],
                'size' => $res['file_size'],
                'path' => $res['file_name'],
                'createtime' => time(),
                'updatetime' => time()
            ];

            $addStatus = $this->FilesModel->save($fileDate);
            if ($addStatus === false) {
                $this->FilesModel->rollback();
                unlink($res['file_name']);
                return json(error_ful('上传失败', $res['filename']));
            }

            // 综合判断
            if ($handStatus === false || $addStatus === false) {
                $this->FilesModel->rollback();
                $this->FilesModel->rollback();
                return json(error_ful('上传失败', $res['filename']));
            } else {
                $this->HandleModel->commit();
                $this->FilesModel->commit();

                return json(success_ful('上传成功'));
            }
        }
    }

    //修改文件信息
    public function update()
    {
        if ($this->request->isGet()) {
            $userid = $this->request->param('userid', 0, 'trim');
            $fileid = $this->request->param('fileid', 0, 'trim');
            $proid = $this->request->param('proid', 0, 'trim');
            $filename = $this->request->param('filename', '', 'trim');

            // 检查当前账号权限
            $auth = $this->RelevanceModel->where(['userid' => $userid, 'proid' => $proid])->value('auth');
            if ($auth * 1 < 3) {
                return json(error_ful('您的账号无权限'));
            }

            // 检查文件是否存在
            $fileInfo = $this->FilesModel->where(['id' => $fileid, 'proid' => $proid])->find();
            if (empty($fileInfo)) {
                return json(error_ful('文件不存在'));
            }

            //检查修改的文件名在当前文件夹下是否重名
            if ($filename != $fileInfo['filename']) {
                $where = [
                    'proid' => $proid,
                    'filename' => $filename
                ];
                $doubleName = $this->FilesModel->where($where)->find();
                if (!empty($doubleName)) {
                    return json(error_ful('文件名重复'));
                }
            }

            $status = $this->FilesModel->where('id', $fileInfo['id'])->update(['filename' => $filename]);
            if ($status === false) {
                return json(error_ful('修改失败'));
            } elseif ($status == 0) {
                return json(error_ful('无任何修改'));
            } else {
                return json(success_ful('修改成功'));
            }

        }
    }

    //删除文件,仅项目管理员可以
    public function delete()
    {
        if ($this->request->isGet()) {
            $userid = $this->request->param('userid', 0, 'trim');
            $proid = $this->request->param('proid', 0, 'trim');
            $fileid = $this->request->param('fileid', 0, 'trim');

            $userInfo = $this->UserModel->where('id', $userid)->find();
            if (empty($userInfo)) {
                return json(error_ful('账号不存在'));
            }

            $fileInfo = $this->FilesModel->where('id', $fileid)->find();
            if (empty($fileInfo)) {
                return json(error_ful('文件不存在'));
            }
            $proInfo = $this->ProjectModel->where('id', $proid)->find();
            if (empty($proInfo)) {
                return json(error_ful('项目不存在'));
            }
            $auth = $this->RelevanceModel->where(['userid' => $userid, 'proid' => $proid])->value('auth');
            if ($auth != '4') {
                return json(error_ful('您的权限不足'));
            }

            // 开启事务
            $this->HandleModel->startTrans();
            $this->FilesModel->startTrans();

            $handleDate = [
                'userid' => $userid,
                'time' => time(),
                'proid' => $proid,
                'filename' => $fileInfo['filename'],
                'handtype' => 'delete'
            ];
            $handStatus = $this->HandleModel->save($handleDate);
            if ($handStatus === false) {
                return json(error_ful('记录操作失败'));
            }

            $fileStatus = $this->FilesModel->where('id', $fileid)->update(['deletetime' => time()]);
            if ($fileStatus === false) {
                $this->HandleModel->rollback();
                return json(error_ful('文件删除失败'));
            }

            if ($handStatus === false || $fileStatus === false) {
                $this->HandleModel->rollback();
                $this->FilesModel->rollback();
                return json(error_ful('删除失败'));
            } else {
                unlink($fileInfo['path']);
                $this->HandleModel->commit();
                $this->FilesModel->commit();
                return json(success_ful('删除成功'));
            }
        }
    }

    // 文件移动
    public function remove()
    {
        if ($this->request->isGet()) {
            $token = $this->request->param('token', '', 'trim');
            $parentid = $this->request->param('parentid', null, 'trim');
            $fileid = $this->request->param('fileid', 0, 'trim');
            $proid = $this->request->param('proid', 0, 'trim');

            if($proid == $parentid){
                return json(error_ful('不能移动到自己里面'));
            }
            if (empty($token)) {
                return json(error_ful('权限不足'));
            }
            $userInfo = $this->token->checkToken($token);
            // return json(success_ful('账号信息', $userInfo));
            if ($userInfo['status'] !== 1) {
                return json(error_ful($userInfo['message']));
            }

            // 检查目标文件夹是否存在
            if (!empty($parentid)) {
                $parentProject = $this->ProjectModel->where('id', $parentid)->find();
                if (empty($parentProject)) {
                    return json(error_ful('目标文件夹不存在'));
                }
            }

            if (empty($fileid) && empty($proid)) {
                return json(error_ful('文件不存在'));
            }

            // 移动文件
            if (!empty($fileid)) {
                $data = [
                    'proid' => $parentid ? $parentid : null
                ];

                $fileStatus = $this->FilesModel->where('id', $fileid)->update($data);
                if ($fileStatus === false) {
                    return json(error_ful('移动失败'));
                } elseif ($fileStatus == 0) {
                    return json(error_ful('无任何修改'));
                } else {
                    return json(success_ful('移动成功'));
                }
            }

            // 移动文件夹
            if (!empty($proid)) {
                $data = [
                    'parentid' => $parentid ? $parentid : null,
                ];
                $proStatus = $this->ProjectModel->where('id', $proid)->update($data);
                if ($proStatus === false) {
                    return json(error_ful('移动失败'));
                } elseif ($proStatus == 0) {
                    return json(error_ful('无任何修改'));
                } else {
                    return json(success_ful('移动成功'));
                }
            }
        }
    }

    // 检查已上传的切片
    public function checkUploaded()
    {
        if ($this->request->isPost()) {
            $identifier = $this->request->param('identifier', '', 'trim');
            $proid = $this->request->param('proid', 0, 'trim');
            $token = $this->request->param('token', '', 'trim');

            // 检查文件夹是否存在
            $proInfo = $this->ProjectModel->where('id', $proid)->find();
            if (empty($proInfo)) {
                return json(error_ful('文件夹不存在'));
            }

            //检查账号
            if (empty($token)) {
                return json(error_ful('账号不存在'));
            }
            $userInfo = $this->token->checkToken($token);
            if ($userInfo['status'] == 0) {
                return json(error_ful($userInfo['message']));
            }
            $userid = $userInfo['data']['id'];
            $auth = $this->RelevanceModel->where(['proid' => $proid, 'userid' => $userid])->find();

            if (empty($auth) || $auth['auth'] * 1 < 3) {
                return json(error_ful('账号权限不足'));
            }
            $res = $this->upload->checkUploadedChunks($identifier);
            return json(success_ful('已上传分片序号', $res));
        }
    }

    // 接收分片
    public function uploadChunk()
    {
        if ($this->request->isPost()) {
        }
        $chunk = $this->request->file('chunk');  //分片文件（Resumable.js默认字段名）
        $chunkNumber = $this->request->param('chunknumber'); //当前分片序号（从1开始）
        $totalChunks = $this->request->param('totalchunks'); //分片总数
        $identifier = $this->request->param('identifier'); //文件唯一标识（由前端生成，如MD5哈希）

        $status = $this->upload->chunkUpload($chunk, $chunkNumber, $totalChunks, $identifier);
        return json(success_ful($status));

    }

    public function mergeChunk()
    {
        if ($this->request->isPost()) {
            $identifier = $this->request->param('identifier', '', 'trim');
            $filename = $this->request->param('filename', '', 'trim');
            $totalChunks = $this->request->param('totalchunks', 0, 'trim');
            $proid = $this->request->param('proid', 0, 'trim');
            $token = $this->request->param('token', '', 'trim');

            if (empty($token)) {
                return json(error_ful('账号不存在'));
            }
            $userInfo = $this->token->checkToken($token);
            if ($userInfo['status'] === 0) {
                return json($userInfo['message']);
            }
            $userid = $userInfo['data']['id'];
            // 检查文件夹
            $proInfo = $this->ProjectModel->where('id', $proid)->find();
            if (empty($proInfo)) {
                return json(error_ful('文件夹不存在'));
            }

            $saveDir = './' . $proInfo['backage'];
            $res = $this->upload->mergeChunks($identifier, $totalChunks, $filename, $saveDir);
            if ($res['status'] === 0) {
                return json(error_ful($res['msg']));
            }
            $savePath = $res['data']['savePath'];

            $handleDate = [
                'userid' => $userid,
                'time' => time(),
                'proid' => $proid,
                'filename' => $res['data']['basename'],
                'handtype' => 'upload'
            ];

            $handStatus = $this->HandleModel->save($handleDate);
            if ($handStatus === false) {
                if (file_exists($savePath))
                    unlink($savePath);

                return json(error_ful('记录操作失败'));
            }

            $filename = $proInfo['backage'] . $res['data']['filename'];
            // 写入数据库
            $filesData = [
                'filename' => $res['data']['basename'],
                'proid' => $proid,
                'suffix' => $res['data']['extension'],
                'size' => $res['data']['size'],
                'path' => $filename,
                'createtime' => time(),
                'updatetime' => time()
            ];
            $fileStatus = $this->FilesModel->insert($filesData);
            if ($fileStatus === false || $fileStatus == 0) {
                if (file_exists($savePath)) {
                    unlink($savePath);
                }
                return json(error_ful('上传失败'));
            }

            return json(success_ful('合并成功'));
        }
    }
}